{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Table of Contents\n", "* [1. From Bouncing Ball to Angry Birds](#1.-From-Bouncing-Ball-to-Angry-Birds)\n", "\t* [1.1 A Ball](#1.1-A-Ball)\n", "\t* [1.2 Global Variables](#1.2-Global-Variables)\n", "\t* [1.3 Brownian Motion](#1.3-Brownian-Motion)\n", "\t* [1.4 Velocity](#1.4-Velocity)\n", "\t\t* [1.4.1 Bouncing off the walls](#1.4.1-Bouncing-off-the-walls)\n", "\t\t* [1.4.2 Gravity](#1.4.2-Gravity)\n", "\t\t* [1.4.3 Dampening](#1.4.3-Dampening)\n", "\t* [1.5 Interactivity](#1.5-Interactivity)\n", "\t* [1.6 Angry Birds](#1.6-Angry-Birds)\n", "\t* [1.7 Conclusion](#1.7-Conclusion)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 1. From Bouncing Ball to Angry Birds" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook explores the idea that objects on our sketch appear to move in various ways:\n", "\n", "* Falls\n", "* Projectiles\n", "* Bounces\n", "\n", "This is a magic trick... nothing really \"moves\"... it is just the canvas redrawn in an appropriate way that gives the illusion of movement." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.1 A Ball" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Like we did for Lab 2, let's draw an object at a specific location:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_1\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_1\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_1\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_1\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #1:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #1 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "void setup() {\n", " size(200, 200);\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "void draw() {\n", " drawBall(100, 20, 1);\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.2 Global Variables" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, we'll create two global variables, and initialize them to the same values as above:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_2\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_2\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_2\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_2\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #2:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #2 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "float x = 100;\n", "float y = 20;\n", "\n", "void setup() {\n", " size(200, 200);\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "void draw() {\n", " drawBall(x, y, 1);\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's move the assignment to the setup() function:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_4\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_4\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_4\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_4\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #4:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #4 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "float x;\n", "float y;\n", "\n", "void setup() {\n", " size(400, 100);\n", " x = width/2;\n", " y = 20;\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "void draw() {\n", " drawBall(x, y, 1);\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nothing too interesting there. I did use the special variables `width` and `height` that are automatically defined to be the size of the canvas. But other than that, it is just a picture of a red ball sitting quietly in space." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.3 Brownian Motion" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's try a slight variation. Do you know the idea of [Brownian Motion](http://en.wikipedia.org/wiki/Brownian_motion) (sometimes called _particle theory_). This is basically just the idea that small objects will randomly move because they are hit will atoms or molecules. \n", "\n", "**Warning**: _I did not say \"Brownie in motion\"... that is a small chocolate treat that is on the move._\n", "\n", "We can simulate Brownian Motion by simply moving the ball a little left, right, or stay in the same place. We use the fact that `random(2) - 1` represents either a -1, 0, or 1." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_5\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_5\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_5\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_5\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #5:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #5 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "-0.7309886215007491\n", "0.901475877332913\n" ] } ], "source": [ "println(random(2) - 1);" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "format": "column" }, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_7\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_7\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_7\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_7\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #7:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #7 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "// Global variables: \n", "// defined here, used in setup() and draw()\n", "\n", "float x;\n", "float y;\n", "\n", "void setup() {\n", " size(200, 200);\n", " x = width/2;\n", " y = height/2;\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " stroke(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "void draw() {\n", " drawBall(x, y, 1);\n", " x = x + random(2) - 1;\n", " y = y + random(2) - 1;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It looks like the ball is moving randomly about, doesn't it. You can make the effect even stronger by clearing the background before you redraw the ball:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_14\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_14\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_14\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_14\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #14:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #14 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "// Global variables: \n", "// defined here, used in setup() and draw()\n", "\n", "float x;\n", "float y;\n", "\n", "void setup() {\n", " size(200, 200);\n", " x = width/2;\n", " y = height/2;\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "void draw() {\n", " background(168);\n", " drawBall(x, y, 1);\n", " x = x + random(3) - 1;\n", " //y = y + 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.4 Velocity" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, instead of having the ball randomly move each time step, let's have the ball move in a particular direct. To do this, we will create two new variables that will keep track of the velocity (speed) of the ball in the x and y directions.\n", "\n", "On each time step, we will move the ball an appropriate amount." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_17\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_17\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_17\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_17\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #17:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #17 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "// Give the ball velocities \n", "// in the x and y directions:\n", "\n", "float vx;\n", "float vy;\n", "\n", "float x;\n", "float y;\n", "\n", "float dt; \n", "float t;\n", "\n", "void setup() {\n", " size(200, 200);\n", " x = width/2;\n", " y = 50;\n", " dt = 0.1; \n", " t = 0;\n", " vx = 1.0;\n", " vy = 0.0;\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "void draw() {\n", " background(128, 128, 128);\n", " float dx = vx * dt; \n", " x = x + dx;\n", " \n", " float dy = vy * dt;\n", " y = y + dy;\n", "\n", " drawBall(x, y, 1);\n", " \n", " t = t + dt;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Somewhat interesting... but where did it go?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.4.1 Bouncing off the walls" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To keep the ball \"on the canvas\", we need to see when it is beyond bounds, and turn the ball around. All we need to do is switch the velocity to go in the opposite direction. So if the ball is going to the right and hits a wall, we make it go to the left.\n", "\n", "To allow the ball to do one thing if it hits a wall, and something else if it doesn't we need to introduce the idea of *flow of control*.\n", "\n", "We can control the *flow* of a program using if/else, like this:\n", "\n", "```java\n", "if (EXPRESSION) {\n", " STATEMENT;\n", " ...\n", "} else {\n", " STATEMENT;\n", " ...\n", "}\n", "```" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_20\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_20\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_20\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_20\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #20:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #20 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "float vx;\n", "float vy;\n", "\n", "float x;\n", "float y;\n", "\n", "float dt; \n", "float t;\n", "\n", "void setup() {\n", " size(200, 200);\n", " x = width/2;\n", " y = 50;\n", " dt = 0.1; \n", " t = 0;\n", " vx = 10.0;\n", " vy = 7.5;\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 50 * scale, 50 * scale);\n", "}\n", "\n", "void draw() {\n", " background(0, 255, 0);\n", " float dx = vx * dt; \n", " if (((x + dx) > width) || ((x + dx) < 0)) {\n", " vx = vx * -1;\n", " } else {\n", " x = x + dx;\n", " }\n", " \n", " float dy = vy * dt;\n", " if (((y + dy) > height) || ((y + dy) < 0)) {\n", " vy = vy * -1;\n", " } else {\n", " y = y + dy;\n", " }\n", "\n", " drawBall(x, y, 1);\n", " \n", " t = t + dt;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.4.2 Gravity" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, the final step: let's add gravity. At each timestep, we'll add a gravity component to vy. Over time, that will get bigger and bigger." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_22\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_22\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_22\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_22\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #22:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #22 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "float g = 9.8; \n", "\n", "float vx;\n", "float vy;\n", "\n", "float x;\n", "float y;\n", "\n", "float dt; \n", "float t;\n", "\n", "void setup() {\n", " size(200, 500);\n", " x = width/2;\n", " y = 50;\n", " dt = 0.1; \n", " t = 0;\n", " vx = 5.0;\n", " vy = 0.0;\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "void draw() {\n", " //background(0, 0, 128);\n", " // gravity\n", " vy = vy + g * dt;\n", " \n", " float dx = vx * dt; \n", " if (((x + dx) > width) || ((x + dx) < 0)) {\n", " vx = vx * -1;\n", " } else {\n", " x = x + dx;\n", " }\n", " \n", " float dy = vy * dt;\n", " if (((y + dy) > height) || ((y + dy) < 0)) {\n", " vy = vy * -1;\n", " } else {\n", " y = y + dy;\n", " }\n", "\n", " drawBall(x, y, 1);\n", " \n", " t = t + dt;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.4.3 Dampening" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That is weird... it keeps bouncing! We probably want to lose a little bit of energy each time it \"hits something.\" We merely don't give the full amount when we change directions." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_25\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_25\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_25\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_25\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #25:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #25 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "float g = 9.8; \n", "\n", "float vx;\n", "float vy;\n", "\n", "float x;\n", "float y;\n", "\n", "float dt; \n", "float t;\n", "\n", "void setup() {\n", " size(200, 500);\n", " x = width/2;\n", " y = 50;\n", " dt = 0.1; \n", " t = 0;\n", " vx = 50.0;\n", " vy = 0.0;\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "void draw() {\n", " // gravity\n", " background(255);\n", " vy = vy + g * dt;\n", " \n", " float dx = vx * dt; \n", " if (((x + dx) > width) || ((x + dx) < 0)) {\n", " vx = vx * -0.6;\n", " } else {\n", " x = x + dx;\n", " }\n", " \n", " float dy = vy * dt;\n", " if (((y + dy) > height) || ((y + dy) < 0)) {\n", " vy = vy * -0.6;\n", " } else {\n", " y = y + dy;\n", " }\n", "\n", " drawBall(x, y, 1);\n", " \n", " t = t + dt;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.5 Interactivity" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nice! Now let's drop the ball with the mouse:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_26\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_26\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_26\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_26\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #26:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #26 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "float g = 9.8; \n", "\n", "float vx;\n", "float vy;\n", "\n", "float x;\n", "float y;\n", "\n", "float dt; \n", "float t;\n", "\n", "void setup() {\n", " size(200, 500);\n", " x = width/2;\n", " y = 50;\n", " dt = 0.1; \n", " t = 0;\n", " vx = 50.0;\n", " vy = 0.0;\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "void draw() {\n", " // gravity\n", " background(168);\n", " vy = vy + g * dt;\n", " \n", " float dx = vx * dt; \n", " if (((x + dx) > width) || ((x + dx) < 0)) {\n", " vx = vx * -0.8;\n", " } else {\n", " x = x + dx;\n", " }\n", " \n", " float dy = vy * dt;\n", " if (((y + dy) > height) || ((y + dy) < 0)) {\n", " vy = vy * -0.8;\n", " } else {\n", " y = y + dy;\n", " }\n", "\n", " drawBall(x, y, 1);\n", " \n", " t = t + dt;\n", "}\n", "\n", "void mousePressed() {\n", " x = mouseX;\n", " y = mouseY;\n", " vx = 0.0;\n", " vy = 0.0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.6 Angry Birds" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, but it just drops. What if we could click, drag, and release, and the distance we dragged was proportional to a vector in the opposite direction of where we want to send it. Angry Birds!\n", "\n", "Click below and drag:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", " var component = document.getElementById(\"sketch_31\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"state_31\");\n", " if (component != undefined)\n", " component.remove();\n", " component = document.getElementById(\"controls_div_31\");\n", " if (component != undefined)\n", " component.remove();\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " // FIXME: Stop all previously running versions (?)\n", " var processingInstance = Processing.getInstanceById(\"canvas_31\");\n", " if (processingInstance != undefined && processingInstance.isRunning())\n", " processingInstance.noLoop();\n", " });\n", "\n", "\n", " var output_area = this;\n", " // find my cell element\n", " var cell_element = output_area.element.parents('.cell');\n", " // which cell is it?\n", " var cell_idx = Jupyter.notebook.get_cell_elements().index(cell_element);\n", " // get the cell object\n", " var cell = Jupyter.notebook.get_cell(cell_idx);\n", "\n", " function jyp_print(cell, newline) {\n", " return function(message) {\n", " cell.get_callbacks().iopub.output({header: {\"msg_type\": \"stream\"},\n", " content: {text: message + newline,\n", " name: \"stdout\"}});\n", " }\n", " }\n", " window.jyp_println = jyp_print(cell, \"\\n\");\n", " window.jyp_print = jyp_print(cell, \"\");\n", "\n", " require([window.location.protocol + \"//calysto.github.io/javascripts/processing/processing.js\"], function() {\n", " Processing.logger.println = jyp_print(cell, \"\\n\");\n", " Processing.logger.print = jyp_print(cell, \"\");\n", " });\n", "\n", "\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " Sketch #31:
\n", "
\n", "
\n", "
\n", " \n", " \n", " \n", " \n", "
\n", "Sketch #31 state: Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "float g = 9.8; \n", "\n", "float vx;\n", "float vy;\n", "\n", "float x;\n", "float y;\n", "\n", "float dt; \n", "float t;\n", "\n", "void setup() {\n", " size(500, 500);\n", " x = width/2;\n", " y = 50;\n", " dt = 0.2; \n", " t = 0;\n", " vx = 0.0;\n", " vy = 0.0;\n", " background(255);\n", "}\n", "\n", "void drawBall(float x, float y, float scale) {\n", " fill(255, 0, 0);\n", " ellipse(x, y, 10 * scale, 10 * scale);\n", "}\n", "\n", "boolean mouseIsDown = true;\n", "\n", "void draw() {\n", " if (mouseIsDown) return;\n", " background(255);\n", " \n", " // gravity\n", " vy = vy + g * dt;\n", " \n", " float dx = vx * dt; \n", " if (((x + dx) > width) || ((x + dx) < 0)) {\n", " vx = vx * -0.8;\n", " } else {\n", " x = x + dx;\n", " }\n", " \n", " float dy = vy * dt;\n", " if (((y + dy) > height) || ((y + dy) < 0)) {\n", " vy = vy * -0.8;\n", " if (abs(vy) > 30) {\n", " //drawBall(x, y, 2);\n", " fill(255, 0,0);\n", " ellipse(x, y, vy, 5);\n", " noLoop();\n", " return;\n", " }\n", " } else {\n", " y = y + dy;\n", " }\n", "\n", " drawBall(x, y, 1);\n", " \n", " t = t + dt;\n", "}\n", "\n", "void mousePressed() {\n", " mouseIsDown = true;\n", " x = mouseX;\n", " y = mouseY;\n", " background(255);\n", " drawBall(x, y, 1);\n", " vx = 0.0;\n", " vy = 0.0;\n", "}\n", "\n", "void mouseReleased() {\n", " vx = (x - mouseX);\n", " vy = (y - mouseY);\n", " mouseIsDown = false;\n", " loop();\n", "}\n", "\n", "void mouseDragged() {\n", " background(255);\n", " drawBall(x, y, 1);\n", " line(x, y, mouseX, mouseY);\n", "}" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "To make a really \"angry birds\" like game, we'll need to detect more than collisions with the walls, floor, and ceiling. We'll do that later, once we learn how to make real objects." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1.7 Conclusion" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this notebook we have seen that motion is just imagined. We saw Brownian Motion, velocity, gravity, and a ball with an applied force (ala Angry Birds).\n", "\n", "**New ideas and jargon**:\n", "\n", "* global variable\n", "* perceived motion\n", "* gravity\n", "* bounce\n", "* flow of control\n", "* if/else\n", "* interactivity\n", "* statement versus expression" ] } ], "metadata": { "kernelspec": { "display_name": "Calysto Processing", "language": "java", "name": "calysto_processing" }, "language_info": { "codemirror_mode": { "name": "text/x-java", "version": 2 }, "file_extension": ".java", "mimetype": "text/x-java", "name": "java" } }, "nbformat": 4, "nbformat_minor": 1 }